package com.loren.demo03.websocket;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
import io.netty.handler.stream.ChunkedWriteHandler;

public class WebSocketServer {

    private static final int WEB_SOCKET_PORT = 9000;

    public static void main(String[] args) {
        // 定义主线程组
        EventLoopGroup parentGroup = new NioEventLoopGroup();
        // 定义从线程组
        EventLoopGroup childGroup = new NioEventLoopGroup();
        try {
            // Netty服务器的创建，ServerBootstrap 是一个启动类
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(parentGroup, childGroup)    // 设置主从县城
                    .channel(NioServerSocketChannel.class)    // 设置NIO的双向通道
                    .option(ChannelOption.SO_BACKLOG, 1024)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) {
                            // 获取对应的Pipeline
                            ChannelPipeline channelPipeline = socketChannel.pipeline();

                            // 向Pipeline添加处理器

                            // 基于http协议，要有http编解码器
                            channelPipeline.addLast(new HttpServerCodec());
                            // 数据流的支持
                            channelPipeline.addLast(new ChunkedWriteHandler());
                            // 将消息聚合成HttpRequest与HttpResponse
                            channelPipeline.addLast(new HttpObjectAggregator(1024 * 64));

                            // ===================== 以上是用于支持http协议 ===========================

                            // websocket 服务协议 指定给客户端连接访问的路由：/ws
                            channelPipeline.addLast(new WebSocketServerProtocolHandler("/hello"));

                            // 向Pipeline添加自定义的处理器
                            channelPipeline.addLast(new WebSocketServerHandler());
                        }
                    });// 子处理器，用于处理childGroup

            // 启动服务，设置端口号为9000，同时启动方式为同步
            ChannelFuture channelFuture = serverBootstrap.bind(WEB_SOCKET_PORT).sync();

            System.out.println("Web Server listening port is " + WEB_SOCKET_PORT);

            // 对关闭通道进行监听
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            childGroup.shutdownGracefully();
            parentGroup.shutdownGracefully();
        }
    }
}
